/**
 * CAgent Sidecar Type Definitions
 * 
 * Core types for the Bun Runtime Sidecar
 */

import type { z } from 'zod';

// ============================================================================
// Agent Types
// ============================================================================

export type ClaudeModel = 
  | 'claude-opus-4'
  | 'claude-sonnet-4'
  | 'claude-sonnet-4.5'
  | 'claude-haiku-4';

export type PermissionMode = 'default' | 'allow_all' | 'deny_all' | 'prompt';

export type SettingSource = 'user' | 'project' | 'local';

export interface AgentOptions {
  model?: ClaudeModel;
  systemPrompt?: string | { type: 'preset'; preset: 'claude_code'; append?: string };
  maxTurns?: number;
  maxTokens?: number;
  includePartialMessages?: boolean;
  permissionMode?: PermissionMode;
  settingSources?: SettingSource[];
  allowedTools?: string[];
  disallowedTools?: string[];
  mcpServers?: Record<string, McpServerConfig>;
  agents?: Record<string, SubAgentSdkConfig> | undefined; // Sub-agents configuration
  enableSubAgents?: boolean; // Enable/disable sub-agents (default: true)
  subAgentId?: string; // Specific sub-agent to use (if set, only this sub-agent will be available)
  continue?: boolean;
  resume?: string;
}

/**
 * Sub-Agent SDK configuration
 * Format expected by Claude Agent SDK's `agents` parameter
 */
export interface SubAgentSdkConfig {
  description: string;
  prompt: string;
  tools?: string[];
  model?: 'sonnet' | 'opus' | 'haiku' | 'inherit';
}

export interface QueryRequest {
  prompt: string | AsyncIterable<UserMessage>;
  options?: AgentOptions;
  sessionId?: string;
}

export interface QueryResponse {
  type: 'assistant' | 'stream_event' | 'result' | 'error' | 'subagent_event';
  content?: string;
  event?: StreamEvent | 'start' | 'end';
  result?: any;
  error?: ErrorInfo;
  sessionId?: string;
  agentId?: string; // Sub-agent ID for subagent_event type
  agentName?: string; // Sub-agent name for subagent_event type
}

// ============================================================================
// Message Types
// ============================================================================

export interface UserMessage {
  role: 'user';
  content: string | MessageContent[];
}

export type MessageContent = TextContent | ImageContent;

export interface TextContent {
  type: 'text';
  text: string;
}

export interface ImageContent {
  type: 'image';
  source: {
    type: 'base64';
    media_type: 'image/png' | 'image/jpeg' | 'image/gif' | 'image/webp';
    data: string;
  };
}

export interface StreamEvent {
  type: 'message_start' | 'content_block_start' | 'content_block_delta' | 'content_block_stop' | 'message_delta' | 'message_stop';
  delta?: {
    type: 'text_delta';
    text: string;
  };
}

// ============================================================================
// Tool Types
// ============================================================================

export interface ToolDefinition {
  name: string;
  description: string;
  inputSchema: z.ZodObject<any>;
  handler: (args: any, extra?: any) => Promise<CallToolResult>;
}

export interface CallToolResult {
  content: Array<{
    type: 'text';
    text: string;
  }>;
}

// ============================================================================
// MCP Types
// ============================================================================

export type McpServerConfig = 
  | McpStdioServerConfig
  | McpSSEServerConfig
  | McpHttpServerConfig
  | McpSdkServerConfig;

export interface McpStdioServerConfig {
  type: 'stdio';
  command: string;
  args?: string[];
  env?: Record<string, string>;
}

export interface McpSSEServerConfig {
  type: 'sse';
  url: string;
  headers?: Record<string, string>;
}

export interface McpHttpServerConfig {
  type: 'http';
  url: string;
  headers?: Record<string, string>;
}

export interface McpSdkServerConfig {
  type: 'sdk';
  name: string;
  version?: string;
  tools?: ToolDefinition[];
}

// ============================================================================
// Session Types
// ============================================================================

export interface Session {
  id: string;
  createdAt: Date;
  updatedAt: Date;
  agentOptions: AgentOptions;
  messages: Message[];
  metadata?: Record<string, any>;
}

export interface Message {
  id: string;
  role: 'user' | 'assistant' | 'system';
  content: string;
  timestamp: Date;
  metadata?: Record<string, any>;
}

// ============================================================================
// Error Types
// ============================================================================

export interface ErrorInfo {
  code: string;
  message: string;
  details?: any;
}

export class AgentError extends Error {
  constructor(
    public code: string,
    message: string,
    public details?: any
  ) {
    super(message);
    this.name = 'AgentError';
  }
}

// ============================================================================
// API Types
// ============================================================================

export interface ApiResponse<T = any> {
  success: boolean;
  data?: T;
  error?: ErrorInfo;
  timestamp: string;
}

export interface HealthCheckResponse {
  status: 'healthy' | 'unhealthy';
  version: string;
  uptime: number;
  timestamp: string;
}

// ============================================================================
// Configuration Types
// ============================================================================

export interface Config {
  // API Configuration
  anthropicApiKey: string;
  
  // Server Configuration
  port: number;
  host: string;
  
  // Agent Configuration
  defaultModel: ClaudeModel;
  maxTurns: number;
  maxTokens: number;
  
  // MCP Configuration
  mcpServersDir: string;
  
  // Security
  enableCors: boolean;
  allowedOrigins: string[];
  
  // Performance
  enableCache: boolean;
  cacheTtl: number;
  
  // Logging
  logLevel: 'debug' | 'info' | 'warn' | 'error';
}

// ============================================================================
// Utility Types
// ============================================================================

export type Awaitable<T> = T | Promise<T>;

export type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};

export type NonNullableFields<T> = {
  [P in keyof T]-?: NonNullable<T[P]>;
};

